package com.iqilu.ksd.activity.live;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.iqilu.ksd.R;
import com.iqilu.ksd.activity.BaseActivity;
import com.iqilu.ksd.utils.BaseUtils;
import com.iqilu.ksd.utils.CacheUtils;
import com.iqilu.ksd.utils.ConvertUtils;
import com.iqilu.ksd.utils.ImageUtils;
import com.iqilu.ksd.utils.ScreenUtils;

import java.io.IOException;
import java.util.List;

/**
 * Created by Coofee on 2016/11/24.
 */

public class SmallVideoActivity extends BaseActivity {

    private static final String TAG = "SmallVideoActivity";

    private Camera mCamera;
    private int cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    private MediaRecorder mediaRecorder;
    private SurfaceHolder holder;
    private boolean isRecording;
    private boolean isCancel;
    private ProgressDialog progressDialog;
    private int id;
    private String path;
    private String fileName;
    private int width;
    private int height;
    private boolean isUploading;

    private ValueAnimator va;

    private SurfaceView mSurfaceView;
    private LinearLayout layLine;
    private ImageView btRecord;
    private ImageView imgCancel;
    private FrameLayout laySurface;
    private ImageView btFlip;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_smallvideo);
        initView();
        path = CacheUtils.getVideoDir(this);
        id = getIntent().getIntExtra("id", 0);

        width = ScreenUtils.getScreenWidth(this);
        height = width / 3 * 4;
        ViewGroup.LayoutParams params = mSurfaceView.getLayoutParams();
        params.width = width;
        params.height = height;
        mSurfaceView.setLayoutParams(params);
        ViewGroup.LayoutParams fParams = laySurface.getLayoutParams();
        fParams.width = width;
        fParams.height = width;
        laySurface.setLayoutParams(fParams);

        btRecord.setOnTouchListener(new MyOnTouchListener());
        initCamera();
        holder = mSurfaceView.getHolder();
        holder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                try {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                closeCamera();
            }
        });
    }


    private void initView(){
        mSurfaceView = getView(R.id.mSurfaceView);
        layLine = getView(R.id.lay_line);
        btRecord = getView(R.id.bt_record);
        imgCancel = getView(R.id.img_cancel);
        laySurface = getView(R.id.lay_surface);
        btFlip = getView(R.id.bt_flip);
        btFlip.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                toFlip();
            }
        });
    }

    private void toFlip() {
        if (va != null && va.isRunning()) {
            return;
        }
        closeCamera();
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            cameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
        } else {
            cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
        }
        initCamera();
        try {
            mCamera.setPreviewDisplay(mSurfaceView.getHolder());
        } catch (IOException e) {
            e.printStackTrace();
        }
        mCamera.startPreview();
    }

    private void initCamera() {
        mCamera = Camera.open(cameraId);
        Camera.Parameters parameters = mCamera.getParameters();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        Camera.Size previewSize = getOptimalPreviewSize(previewSizes, width, height);
//        Log.i(TAG, "width=" + width + ";height=" + height);
        parameters.setPreviewSize(previewSize.width, previewSize.height);
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            parameters.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO); //设置场景
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); //关闭闪光灯
        }
        mCamera.setParameters(parameters);
        mCamera.setDisplayOrientation(90);
    }

    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    private void initVideo(String path) {
        mediaRecorder = new MediaRecorder();
        mediaRecorder.reset();
        mCamera.unlock();
        mediaRecorder.setPreviewDisplay(holder.getSurface());
        mediaRecorder.setCamera(mCamera);
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mediaRecorder.setOrientationHint(90);
        } else {
            mediaRecorder.setOrientationHint(270);
        }
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
//        CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
        CamcorderProfile profile = getBaseRecordingProfile();
        mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
        mediaRecorder.setVideoEncodingBitRate(2 * profile.videoFrameWidth * profile.videoFrameHeight);
//        mediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
//        mediaRecorder.setVideoFrameRate(50);
        mediaRecorder.setPreviewDisplay(holder.getSurface());
        mediaRecorder.setOutputFile(path);
        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
            isRecording = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private CamcorderProfile getBaseRecordingProfile() {
        CamcorderProfile returnProfile;
        if (Build.MODEL.startsWith("Le")) {
            return CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
        }
        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
            returnProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
        } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
            returnProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
        } else {
            returnProfile = getDefaultRecordingProfile();
        }
        return returnProfile;
    }

    private CamcorderProfile getDefaultRecordingProfile() {
        CamcorderProfile highProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        if (highProfile != null) {
            return highProfile;
        }
        CamcorderProfile lowProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
        if (lowProfile != null) {
            return lowProfile;
        }
        throw new RuntimeException("No quality level found");
    }

    private void closeCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private void stopRecord() {
        if (isRecording && mediaRecorder != null) {
            mediaRecorder.setOnErrorListener(null);
            mediaRecorder.setPreviewDisplay(null);
            try {
                mediaRecorder.stop();
            } catch (Exception e) {

            }
            mediaRecorder.release();
            mediaRecorder = null;
        }
        if (mCamera != null) {
            mCamera.lock();
        }
        isRecording = false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isRecording) {
            stopRecord();
        }
        closeCamera();
    }

    private void startAnimation() {
        va = ObjectAnimator.ofInt(width, 0);
        va.setDuration(10000);
        va.addListener(new Animator.AnimatorListener() {
            long startTime, endTime;

            @Override
            public void onAnimationStart(Animator animation) {
                startTime = System.currentTimeMillis();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.i(TAG, "onAnimationEnd");
                endTime = System.currentTimeMillis();
                stopRecord();
                if (!isCancel) {
                    if (endTime - startTime >= 1000) {
//                        new UploadThread().execute();
                        toVideo();
                    } else if (!isUploading) {
                        Toast.makeText(SmallVideoActivity.this, R.string.live_video_short, Toast.LENGTH_SHORT).show();
                    }
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                ViewGroup.LayoutParams params = layLine.getLayoutParams();
                params.width = value;
                params.height = ConvertUtils.dp2px(SmallVideoActivity.this, 2);
                layLine.setLayoutParams(params);
                layLine.requestLayout();
            }
        });
        va.start();
    }

    private void stopAnimation() {
        va.end();
    }

    class MyOnTouchListener implements View.OnTouchListener {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.i(TAG, "ACTION_DOWN");
                    fileName = "" + System.currentTimeMillis() + ".mp4";
                    initVideo(path + fileName);
                    startAnimation();
                    imgCancel.setVisibility(View.VISIBLE);
                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.i(TAG, "ACTION_MOVE");
                    Log.i(TAG, "ACTION_MOVE_Y=" + event.getY());
                    if (event.getY() < 0) {
//                        imgCancel.setVisibility(View.VISIBLE);
                        isCancel = true;
                    } else {
//                        imgCancel.setVisibility(View.GONE);
                        isCancel = false;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    Log.i(TAG, "ACTION_UP");
//                    stopRecord();
                    stopAnimation();
                    imgCancel.setVisibility(View.GONE);
                    isCancel = false;
                    break;
            }
            return true;
        }
    }

    private void toVideo() {
        String videoPath = path + fileName;
        String name = System.currentTimeMillis() + ".jpg";
        String thumbpath = CacheUtils.getCacheDir(SmallVideoActivity.this) + name;
        Bitmap bitmap = BaseUtils.getVideoThumbnail(videoPath);
        ImageUtils.save(bitmap, thumbpath, Bitmap.CompressFormat.JPEG);

        Intent intent = new Intent(SmallVideoActivity.this, VideoActivity.class);
        intent.putExtra("id", id);
        intent.putExtra("videoPath", videoPath);
        intent.putExtra("thumbpath", thumbpath);
        startActivity(intent);
        finish();
    }
}